#include<iostream>
#include<string>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string>
#include<cstring>
#include<cstdlib>
#include<unistd.h>
#include<signal.h>
#include<pthread.h>

void ServiceIO(int new_sock)
{
    //render server  
    while(true)
    {
      //operator file
      char buffer[1024] = {0};
      ssize_t s = read(new_sock,buffer,sizeof(buffer)-1);
      if(s > 0)
      {
        buffer[s] = 0;
        std::cout << "client# " << buffer << std::endl;
        std::string s = ">>>server<<<, ";
        s += buffer;
        write(new_sock,s.c_str(),s.size());
      }
      else if(s == 0)
      {
        //quit
        std::cout<<"client quit....."<<std::endl;
        break;
      }
      else 
      {
        //erro
        std::cout<<"read error"<<std::endl;
        break;
      }
    }
}


void* HandlerRequest(void* args)
{
  pthread_detach(pthread_self());
  int sock = *(int*)args;
  delete (int*)args;
  ServiceIO(sock);
  close(sock);

}


void Usge(std::string s)
{
  std::cout<<s<<" "<< "port"<<std::endl;
}


int main(int argc,char* argv[])
{
  if(argc != 2)
  {
    Usge(argv[0]);
    return 1;
  }
  
  u_int16_t port = atoi(argv[1]);

  //create listening socket
  int list_sock = socket(AF_INET,SOCK_STREAM,0);
  if(list_sock < 0)
  {
    std::cout<<"socket failed"<<std::endl;
    return 2;
  }

  //bind socket 
  struct sockaddr_in local;
  memset(&local,0,sizeof(local)); 
  local.sin_family = AF_INET; 
  local.sin_port = htons(port);
  local.sin_addr.s_addr = INADDR_ANY;
  
  //bind 
  if(bind(list_sock,(struct sockaddr*)&local,sizeof(local)) < 0)
  {
    //std::cout<<"failed"<<std::endl;
    return 3;
  }

  //set listen 
  if(listen(list_sock,5) < 0)
  {
    std::cout<<"listen error" <<std::endl;
    return 4;
  }

  signal(SIGCHLD,SIG_IGN);

  //connect server 
  while(true)
  {
    struct sockaddr_in peer;
    socklen_t len = sizeof(peer);
    //wait connect
    int new_sock = accept(list_sock,(struct sockaddr*)&peer,&len); 
    if(new_sock < 0)
    {
      std::cout<<"connect erreo"<<std::endl;
      return 5;
    }

    pthread_t tid;
    int* sk = new int(new_sock);
    pthread_create(&tid,nullptr,HandlerRequest,(void*)sk);

  }

  
  return 0;
}


